/*
 * AIEngine a new generation network intrusion detection system.
 *
 * Copyright (C) 2013-2023  Luis Campo Giralte
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 *
 * Written by Luis Campo Giralte <luis.camp0.2009@gmail.com> 
 *
 */
#include "DNSInfo.h"
#include "DNSQueryTypes.h"

namespace aiengine {

void DNSInfo::reset() { 

	name.reset() ; 
	qtype_ = 0;
	txid_ = 0;
	ttl_ = 0;
	rcode_ = std::numeric_limits<uint16_t>::max();
	items_.clear();
	matched_domain_name.reset(); 
	is_banned_ = false;
}

void DNSInfo::addIPAddress(const char* ipstr) { 
	
	items_.emplace_back(ipstr); 
}

void DNSInfo::addName(const char* name) { 
	
	items_.emplace_back(name); 
}

void DNSInfo::addName(const char *name, int length) {

	items_.emplace_back(name, length);
}

std::ostream& operator<< (std::ostream &out, const DNSInfo &info) {

	// Have to evaluate in terms of performance this 
	// code, in general I dont expect calling this code all the time
	// but you never knows....

	std::string_view type_name = "Unknown";
	const auto entry = DNSQueryTypeToString.find(info.qtype_);
	if (entry != DNSQueryTypeToString.end())
		type_name = entry->second;

	if (info.isBanned()) 
		out << " Banned";

	if (info.name) 
		out << " Domain:" << info.name->name();

	out << " type:" << type_name;

	if (info.rcode_ < std::numeric_limits<uint16_t>::max())
		out << " rcode:" << (int)info.rcode_;

	if (info.txid_ > 0)
		out << " tx:" << info.txid_;

	if (info.ttl_ > 0 and info.ttl_ < std::numeric_limits<uint32_t>::max())
		out << " ttl:" << info.ttl_;

	if (info.items_.size() > 0) {
		std::string comma = "";

		out << " [";
		for (auto &item: info.items_) {
			out << comma << item;
			comma = ", ";
		}
		out << "]";

	}

	return out;
}

nlohmann::json& operator<< (nlohmann::json &out, const DNSInfo &info) {

	out["qtype"] = info.qtype_;

	if (info.isBanned()) 
		out["banned"] = true;

	if (info.name) 
		out["domain"] = info.name->name();

	if (info.items_.size() > 0) 
		out["ips"] = info.items_;

        if (info.matched_domain_name)
                out["matchs"] = info.matched_domain_name->name();

        if (info.txid_ > 0)
                out["tx"] = info.txid_;

        if (info.ttl_ > 0 and info.ttl_ < std::numeric_limits<uint32_t>::max())
                out["ttl"] = info.ttl_;

	if (info.rcode_ < std::numeric_limits<uint16_t>::max())
		out["rcode"] = info.rcode_;

	return out;
}

} // namespace aiengine
